package com.fancy.music.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fancy.common.dto.AlbumBasicInfo;
import com.fancy.common.dto.PageResult;
import com.fancy.music.dto.AlbumDetailDTO;
import com.fancy.music.entity.Album;
import com.fancy.music.entity.Song;
import com.fancy.music.mapper.AlbumMapper;
import com.fancy.music.mapper.SongMapper;
import com.fancy.music.service.AlbumService;
import com.fancy.music.service.ArtistService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class AlbumServiceImpl implements AlbumService {

    private final AlbumMapper albumMapper;
    private final SongMapper songMapper;
    private final ArtistService artistService;

    @Override
    public Album getAlbumDetail(Long albumId) {
        return albumMapper.selectById(albumId);
    }

    @Override
    public AlbumDetailDTO getAlbumDetailWithInfo(Long albumId) {
        Album album = albumMapper.selectById(albumId);
        if (album == null) {
            return null;
        }
        return convertToAlbumDetailDTO(album);
    }

    @Override
    public PageResult<Album> searchAlbums(String keyword, String genre, String language, int page, int size) {
        Page<Album> pageRequest = new Page<>(page, size);
        QueryWrapper<Album> queryWrapper = new QueryWrapper<>();

        if (StringUtils.hasText(keyword)) {
            queryWrapper.and(wrapper ->
                wrapper.like("album_name", keyword)
                       .or()
                       .exists("SELECT 1 FROM t_artist a WHERE a.artist_id = t_album.artist_id AND a.artist_name LIKE CONCAT('%', '" + keyword + "', '%')")
            );
        }

        if (StringUtils.hasText(genre)) {
            queryWrapper.like("genre", genre);
        }

        if (StringUtils.hasText(language)) {
            queryWrapper.eq("language", language);
        }

        queryWrapper.eq("status", 1)
                   .orderByDesc("release_date");

        Page<Album> pageResult = albumMapper.selectPage(pageRequest, queryWrapper);
        return new PageResult<>(pageResult.getRecords(), pageResult.getTotal(),
                               pageResult.getSize(), pageResult.getCurrent());
    }

    @Override
    public PageResult<AlbumDetailDTO> searchAlbumsWithDetails(String keyword, String genre, String language, int page, int size) {
        PageResult<Album> albumPage = searchAlbums(keyword, genre, language, page, size);
        List<AlbumDetailDTO> detailDTOs = albumPage.getRecords().stream()
                .map(this::convertToAlbumDetailDTO)
                .collect(Collectors.toList());
        return new PageResult<>(detailDTOs, albumPage.getTotal(), albumPage.getSize(), albumPage.getCurrent());
    }

    @Override
    public List<Album> getHotAlbums(Integer limit) {
        return albumMapper.selectHotAlbums(limit != null ? limit : 10);
    }

    @Override
    public List<AlbumDetailDTO> getHotAlbumsWithDetails(Integer limit) {
        List<Album> albums = albumMapper.selectHotAlbums(limit != null ? limit : 10);
        return albums.stream()
                .map(this::convertToAlbumDetailDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<Album> getNewAlbums(Integer limit) {
        return albumMapper.selectNewAlbums(limit != null ? limit : 10);
    }

    @Override
    public List<AlbumDetailDTO> getNewAlbumsWithDetails(Integer limit) {
        List<Album> albums = albumMapper.selectNewAlbums(limit != null ? limit : 10);
        return albums.stream()
                .map(this::convertToAlbumDetailDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<Album> getAlbumsByArtistId(Long artistId) {
        return albumMapper.selectByArtistId(artistId);
    }

    @Override
    public List<AlbumDetailDTO> getAlbumsByArtistIdWithDetails(Long artistId) {
        List<Album> albums = albumMapper.selectByArtistId(artistId);
        return albums.stream()
                .map(this::convertToAlbumDetailDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<Album> getAlbumsByGenre(String genre, Integer limit) {
        return albumMapper.selectByGenre(genre);
    }

    @Override
    public List<AlbumDetailDTO> getAlbumsByGenreWithDetails(String genre, Integer limit) {
        List<Album> albums = albumMapper.selectByGenre(genre);
        return albums.stream()
                .map(this::convertToAlbumDetailDTO)
                .collect(Collectors.toList());
    }

    @Override
    public AlbumBasicInfo getAlbumBasicInfo(Long albumId) {
        Album album = albumMapper.selectById(albumId);
        if (album == null) {
            return null;
        }

        AlbumBasicInfo info = new AlbumBasicInfo();
        info.setAlbumId(album.getAlbumId());
        info.setAlbumName(album.getAlbumName());
        info.setArtistId(album.getArtistId());
        info.setCoverUrl(album.getCoverUrl());
        info.setReleaseDate(album.getReleaseDate() != null ? album.getReleaseDate().toString() : null);
        info.setGenre(album.getGenre());
        info.setLanguage(album.getLanguage());
        info.setTrackCount(album.getTrackCount());
        info.setDescription(album.getDescription());

        return info;
    }

    @Override
    public List<AlbumBasicInfo> getAlbumBasicInfoBatch(List<Long> albumIds) {
        if (albumIds == null || albumIds.isEmpty()) {
            return Collections.emptyList();
        }

        List<Album> albums = albumMapper.selectBatchIds(albumIds);
        return albums.stream()
                .map(this::convertToBasicInfo)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public Long createAlbum(Album album) {
        try {
            album.setCreateTime(new Date());
            album.setUpdateTime(new Date());
            album.setStatus(1); // 默认启用
            album.setTrackCount(0); // 初始歌曲数量为0

            albumMapper.insert(album);
            return album.getAlbumId();
        } catch (Exception e) {
            log.error("创建专辑失败", e);
            return null;
        }
    }

    @Override
    @Transactional
    public boolean updateAlbum(Album album) {
        try {
            album.setUpdateTime(new Date());
            return albumMapper.updateById(album) > 0;
        } catch (Exception e) {
            log.error("更新专辑失败", e);
            return false;
        }
    }

    @Override
    @Transactional
    public boolean deleteAlbum(Long albumId) {
        try {
            // 删除专辑前，需要先删除或更新相关歌曲
            QueryWrapper<Song> songWrapper = new QueryWrapper<>();
            songWrapper.eq("album_id", albumId);
            List<Song> songs = songMapper.selectList(songWrapper);

            for (Song song : songs) {
                song.setAlbumId(null); // 将歌曲的专辑ID设为null
                songMapper.updateById(song);
            }

            return albumMapper.deleteById(albumId) > 0;
        } catch (Exception e) {
            log.error("删除专辑失败", e);
            return false;
        }
    }

    @Override
    @Transactional
    public boolean toggleAlbumStatus(Long albumId, Integer status) {
        try {
            Album album = new Album();
            album.setAlbumId(albumId);
            album.setStatus(status);
            album.setUpdateTime(new Date());

            return albumMapper.updateById(album) > 0;
        } catch (Exception e) {
            log.error("切换专辑状态失败", e);
            return false;
        }
    }

    @Override
    @Transactional
    public void updateTrackCount(Long albumId) {
        try {
            QueryWrapper<Song> songWrapper = new QueryWrapper<>();
            songWrapper.eq("album_id", albumId)
                      .eq("status", 1);
            Long trackCount = songMapper.selectCount(songWrapper);

            Album album = new Album();
            album.setAlbumId(albumId);
            album.setTrackCount(trackCount.intValue());
            album.setUpdateTime(new Date());

            albumMapper.updateById(album);
        } catch (Exception e) {
            log.error("更新专辑歌曲数量失败", e);
        }
    }

    private AlbumBasicInfo convertToBasicInfo(Album album) {
        AlbumBasicInfo info = new AlbumBasicInfo();
        info.setAlbumId(album.getAlbumId());
        info.setAlbumName(album.getAlbumName());
        info.setArtistId(album.getArtistId());
        info.setCoverUrl(album.getCoverUrl());
        info.setReleaseDate(album.getReleaseDate() != null ? album.getReleaseDate().toString() : null);
        info.setGenre(album.getGenre());
        info.setLanguage(album.getLanguage());
        info.setTrackCount(album.getTrackCount());
        info.setDescription(album.getDescription());
        return info;
    }

    /**
     * 将Album实体转换为AlbumDetailDTO
     */
    private AlbumDetailDTO convertToAlbumDetailDTO(Album album) {
        AlbumDetailDTO dto = new AlbumDetailDTO();
        dto.setAlbumId(album.getAlbumId());
        dto.setAlbumName(album.getAlbumName());
        dto.setArtistId(album.getArtistId());
        dto.setCoverUrl(album.getCoverUrl());
        dto.setReleaseDate(album.getReleaseDate());
        dto.setGenre(album.getGenre());
        dto.setLanguage(album.getLanguage());
        dto.setRecordCompany(album.getRecordCompany());
        dto.setDescription(album.getDescription());
        dto.setTrackCount(album.getTrackCount());
        dto.setStatus(album.getStatus());
        dto.setCreateTime(album.getCreateTime());
        dto.setUpdateTime(album.getUpdateTime());

        // 获取歌手名称
        try {
            if (album.getArtistId() != null) {
                var artistInfo = artistService.getArtistBasicInfo(album.getArtistId());
                dto.setArtistName(artistInfo != null ? artistInfo.getArtistName() : "未知艺术家");
            } else {
                dto.setArtistName("未知艺术家");
            }
        } catch (Exception e) {
            log.warn("获取歌手信息失败, artistId: {}", album.getArtistId(), e);
            dto.setArtistName("未知艺术家");
        }

        return dto;
    }

    @Override
    public List<String> getAllAlbumGenres() {
        try {
            QueryWrapper<Album> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("status", 1)
                       .isNotNull("genre")
                       .ne("genre", "");

            List<Album> albums = albumMapper.selectList(queryWrapper);

            List<String> genres = albums.stream()
                    .filter(album -> album.getGenre() != null && !album.getGenre().trim().isEmpty())
                    .flatMap(album -> {
                        String[] genreArray = album.getGenre().split("[,，]");
                        return java.util.Arrays.stream(genreArray)
                                .map(String::trim)
                                .filter(genre -> !genre.isEmpty());
                    })
                    .distinct()
                    .sorted()
                    .collect(Collectors.toList());

            // 在最前面添加"全部"选项
            List<String> result = new ArrayList<>();
            result.add("全部");
            result.addAll(genres);
            return result;
        } catch (Exception e) {
            log.error("获取专辑音乐风格失败", e);
            List<String> fallbackResult = new ArrayList<>();
            fallbackResult.add("全部");
            return fallbackResult;
        }
    }

    @Override
    public List<Album> getAlbumsByGenreMatch(String genre, Integer limit) {
        try {
            QueryWrapper<Album> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("status", 1);

            // 如果传入的是"全部"，则不添加音乐风格过滤条件
            if (!"全部".equals(genre)) {
                queryWrapper.and(wrapper -> wrapper.like("genre", genre));
            }

            queryWrapper.orderByDesc("release_date");

            if (limit != null && limit > 0) {
                queryWrapper.last("LIMIT " + limit);
            }

            return albumMapper.selectList(queryWrapper);
        } catch (Exception e) {
            log.error("根据音乐风格获取专辑失败", e);
            return Collections.emptyList();
        }
    }

    @Override
    public List<AlbumDetailDTO> getAlbumsByGenreMatchWithDetails(String genre, Integer limit) {
        List<Album> albums = getAlbumsByGenreMatch(genre, limit);
        return albums.stream()
                .map(this::convertToAlbumDetailDTO)
                .collect(Collectors.toList());
    }

    @Override
    public PageResult<AlbumDetailDTO> searchAlbumsForAdmin(String keyword, String genre, Integer status, int page, int size) {
        try {
            Page<Album> pageRequest = new Page<>(page, size);
            QueryWrapper<Album> queryWrapper = new QueryWrapper<>();

            if (StringUtils.hasText(keyword)) {
                queryWrapper.and(wrapper ->
                    wrapper.like("album_name", keyword)
                           .or()
                           .exists("SELECT 1 FROM t_artist a WHERE a.artist_id = t_album.artist_id AND a.artist_name LIKE CONCAT('%', '" + keyword + "', '%')")
                );
            }

            if (StringUtils.hasText(genre)) {
                queryWrapper.like("genre", genre);
            }

            // 管理员可以查看所有状态的专辑，包括禁用的
            if (status != null) {
                queryWrapper.eq("status", status);
            }

            queryWrapper.orderByDesc("release_date");

            Page<Album> pageResult = albumMapper.selectPage(pageRequest, queryWrapper);
            List<AlbumDetailDTO> detailDTOs = pageResult.getRecords().stream()
                    .map(this::convertToAlbumDetailDTO)
                    .collect(Collectors.toList());

            return new PageResult<>(detailDTOs, pageResult.getTotal(),
                                   pageResult.getSize(), pageResult.getCurrent());
        } catch (Exception e) {
            log.error("管理员搜索专辑失败", e);
            return new PageResult<>(Collections.emptyList(), 0L, (long) size, (long) page);
        }
    }
}
